<?php
/*
 * @Author: your name
 * @Date: 2020-10-20 13:58:29
 * @LastEditTime: 2020-12-28 10:06:19
 * @LastEditors: Please set LastEditors
 * @Description: 模块关系
 * @FilePath: /special/application/adminapiv3/service/module_manage/relation/ModuleRelationService.php
 */
namespace app\adminapiv3\service\module_manage;

use app\common\exception\CustomException;
use app\common\service\platform_manage\ServerAuthService;
use app\common\service\BaseService;
use app\common\service\HostLink;
use app\common\service\HostModuleRelation;
use think\Db;

class ModuleRelationService extends BaseService
{
    protected $module;
    protected $host_id_a = [];
    
    public function __construct()
    {
        $HostModuleRelation = new HostModuleRelation();
        $this->module = $HostModuleRelation->fieldCheck($this->module);
    }
    
    /**
     * @name: 未添加主机列表
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2019-12-02 14:58:01
     */
    public function notAddedHostList ($filterData)
    {
        //获取资产组
        $groupId = $this->getLoginHostGroupId();

        $Host = Db::name('Host')->alias('h')
        ->field('h.id,h.name,h.alias,h.ip,h.system_name,hl.status online')
        ->join('HostModuleRelation hmr', 'hmr.host_id = h.id')
        ->join('HostLink hl', 'h.id=hl.host_id')
        ->where('hmr.'.$this->module, 0)
        ->where('hl.module', 'client')
        ->where('os', '>', 0)
        ->where('group_id', $groupId);
        
        !isset($filterData['name']) || empty($filterData['name']) ? : $Host->whereLike('h.name', '%' . $filterData['name'] . '%');
        !isset($filterData['ip']) || empty($filterData['ip']) ? : $Host->whereLiKe('h.ip', '%' . $filterData['ip'] . '%');
        !isset($filterData['online']) || !is_numeric($filterData['online']) ? : $Host->where('hl.status', $filterData['online']);

        $this->conflictField($Host);

        $return = $Host->order('h.id', 'DESC')->paginate()->toArray();

        $ServerAuthService = new ServerAuthService();
        
        $remainingNum = $ServerAuthService->remainingNum($this->module);
        $return['remianing_number'] = $remainingNum;
        
        return $return;
    }

    /**
     * @name: 添加主机
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2019-12-02 15:10:25
     */
    public function addRelation ()
    {
        $this->host_id_a = $this->getHost('id');
        //检测是否已开启
        $HostModuleRelation = new HostModuleRelation();
        $HostModuleRelation->checkStatus($this->module, 1);
        //检测授权 包括：授权数和授权时间
        $ServerAuthService = new ServerAuthService();
        $ServerAuthService->checkRemaining($this->module,count(array_unique($this->host_id_a)));

        //检测是否冲突;
        $this->checkConflict();

        //检测是否依赖
        $this->checkDepend();

        //添加模块关系
        $this->modifyModuleStatus(1);
        
        //添加模块在线状态
        $HostLink = new HostLink;
        $HostLink->add($this->module, $this->host_id_a);

        //模块初始化
        $this->add();
    }

    /**
     * @name: 修改模块状态
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2020-10-27 17:16:05
     */
    protected function modifyModuleStatus ($status)
    {
        Db::name('HostModuleRelation')->whereIn('host_id', $this->host_id_a)->update([$this->module => $status]);
    }

    /**
     * @name: 从模块中删除主机
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2019-12-02 15:14:30
     */
    public function delRelation ()
    {
        //主动离线
        $this->host_id_a = $this->getHost('id');
        $HostLink = new HostLink();
        $HostLink->offline($this->host_id_a, $this->module);

        $HostModuleRelation = new HostModuleRelation();
        //检测是否已关闭
        $HostModuleRelation->checkStatus($this->module, 0);

        //修改状态
        $this->modifyModuleStatus(0);

        //状态重置
        $this->del();
    }

   /**
    * @name: 检查模块依赖关系
    * @Param: 
    * @Description: 
    * @Author: foo
    * @Date: 2020-10-28 16:08:55
    */ 
   public function checkDepend()
   {
        if ($this->module != 'disguise')
        {
            return true;
        }

        $linuxOs = array_filter($this->getHost('os'), function($os)
        {
            if($os == 2)
            {
                return $os;
            }
        });

        if(empty($linuxOs)){
            return true;
        }
        $host_id_a = array_keys($linuxOs);
        $moduleRelationList = Db::name('HostModuleRelation')->where('host_id','in', $host_id_a)->select();

        $noInit = array_filter($moduleRelationList, function($module){
            if($module['hgshield'] == 0 && $module['netfilter'] == 0){
                return $module['host_id'];
            }
        });

        if (!empty($noInit))
        {
            $msg = '开启系统伪装功能需依赖防火墙模块或函谷盾模块，请先添加对应模块！';
            throw new CustomException($this->hostErrorMessage(array_column($noInit, 'host_id'), $msg), 422);
        }
   }

    /**
    * @name: 检测模块冲突
    * @Param: 
    * @Description: 
    * @Author: foo
    * @Date: 2019-12-04 14:31:05
    */
    public function checkConflict ()
    {
       $host_a = $this->getHost();
       $conflictModule = $this->conflictModule();
       
       $return = 0;
       if(!empty($conflictModule))
       {
            foreach ($host_a as $v)
            {
                $server = Db::name('HostModuleRelation');
                foreach ($conflictModule as $cv)
                {
                    $server->whereOrRaw('host_id='. $v['id'] . ' AND ' . $cv . '=1');
                }

                if ($return += $server->count())
                {
                    $hostStr_a[$v['id']] = $v['id'];
                }
            }

        }
 
       if ($return > 0)
       {
           $conflictModule_s = implode(',', $conflictModule);
           $msg = '主机已存在于' . $conflictModule_s . ' 模块中，请先在' . $conflictModule_s . ' 模块中移除后再添加至本模块！';
           throw new CustomException($this->hostErrorMessage($hostStr_a, $msg), 422);
       }

    }
}